package bot;

import bot.ClientLoader;
import bot.ClientFields;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Array;
import java.util.Properties;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileInputStream;

public class Bot {

	private File slword = new File("./slword.txt");
	public int fightMode;

	public Object getGameGraphics() throws Exception {
		Field gameGraphicsField = ClientLoader.clientClass.getDeclaredField(ClientFields.graphicsClass);
		gameGraphicsField.setAccessible(true);
		return gameGraphicsField.get(ClientLoader.client);
	}

	public Class getNpcCache() throws Exception {
		return ClientLoader.npcCache;
	}

	public void createPacket(int packetId, Object offset) throws Exception {
			Method m = getPacketC()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.createPacket,
							new Class[] { Integer.TYPE, Byte.TYPE });
			m.setAccessible(true);
			Object pid = Integer.valueOf(packetId);
			m.invoke(getPacketC(), pid, offset);
	}

	public void finishPacket(int i) throws Exception {
			Method m = getPacketC()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.sendPacket,
							new Class[] { Integer.TYPE });
			m.setAccessible(true);
			Object voi = Integer.valueOf(i);
			m.invoke(getPacketC(), voi);
	}

	public void addString(String word) throws Exception {
			Method m = getStreamClass()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.addString,
							new Class[] { String.class, Integer.TYPE });
			m.setAccessible(true);
			Object num = Integer.valueOf(15515);
			m.invoke(getStreamClass(), word, num);
	}

	public void addByteInt(int streamData, Object dummyStream) throws Exception {
		try {
			Method m = getStreamClass()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.addByteInt,
							new Class[] { Integer.TYPE, Integer.TYPE });
			m.setAccessible(true);
			Object sdata = Integer.valueOf(streamData);
			m.invoke(getStreamClass(), sdata, dummyStream);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void add2ByteInt(int streamData, Object dummyStream) throws Exception {
			Method m = getStreamClass()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.add2ByteInt,
							new Class[] { Integer.TYPE, Byte.TYPE });
			m.setAccessible(true);
			Object object = Integer.valueOf(streamData);
			m.invoke(getStreamClass(), object, dummyStream);
	}

	public void add22ByteInt(Object streamData, Object iD) throws Exception {
			Method m = getStreamClass()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.add22ByteInt,
							new Class[] { Integer.TYPE, Byte.TYPE });
			m.setAccessible(true);
			m.invoke(getStreamClass(), streamData, iD);
	}

	public void add4ByteInt(int streamOne, Object streamTwo) throws Exception {
			Method m = getStreamClass()
					.getClass()
					.getSuperclass()
					.getDeclaredMethod(ClientMethods.add4ByteInt,
							new Class[] { Integer.TYPE, Integer.TYPE });
			m.setAccessible(true);
			Object stream1 = Integer.valueOf(streamOne);
			m.invoke(getStreamClass(), stream1, streamTwo);
	}

	public Object getPacketC() throws Exception {
		Field field = ClientLoader.clientClass.getDeclaredField(ClientFields.getPacketC);
		field.setAccessible(true);
		return field.get(ClientLoader.client);
	}

	public Object getStreamClass() throws Exception {
		Field streamClassField = getPacketC().getClass().getSuperclass().getDeclaredField(ClientFields.streamClass);
		streamClassField.setAccessible(true);
		return streamClassField.get(getPacketC());
	}

	public Object getOurPlayer() throws Exception {
		Field playerField = ClientLoader.clientClass.getDeclaredField(ClientFields.ourPlayer);
		playerField.setAccessible(true);
		return playerField.get(ClientLoader.client);
	}

	public Object getGameMenu() throws Exception {
		Field field = ClientLoader.clientClass.getDeclaredField(ClientFields.gameMenu);
		field.setAccessible(true);
		return field.get(ClientLoader.client);
	}

	public Object getPlayerValues(int index, String fieldName) {
		try {
			Object playerDef = getPlayer(index);
			Field field = playerDef.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			return field.get(playerDef);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public Object getPlayer(int index) throws Exception {
		Field field = ClientLoader.clientClass.getDeclaredField(ClientFields.playerArray);
		field.setAccessible(true);
		Object playerDef = field.get(ClientLoader.client);
		Object array = Array.get(playerDef, index);
		return array;
	}

	private String eOCRWord;
	private String lastEOCRWord;
	private long modified;

	public void doSleeping() {
		try {
			if (modified < slword.lastModified()) {
				eOCRWord = read();
				modified = slword.lastModified();
			}
			if (!eOCRWord.equals(null) && !eOCRWord.equals(lastEOCRWord)) {
				System.out.println("Word: " + eOCRWord);
				sendSleepingWord(eOCRWord);
				lastEOCRWord = eOCRWord;
				wait(4000);
			}
		} catch (Exception e) { }
	}

	private void sendSleepingWord(String s) throws Exception {
		createPacket(45, (byte)-125);
		addByteInt(42, Integer.valueOf(0));
		addString(s);
		finishPacket(0);
	}

	private String read() {
		try {
			BufferedReader bufferedreader = new BufferedReader(new FileReader(slword));
			String str = bufferedreader.readLine().trim();
			bufferedreader.close();
			return str;
		} catch (Exception e) {
			System.out.println("Error: Could not read slword.txt. Do we have permission?");
			return "";
		}
	}

	public boolean inArray(int[] intArray, int j) {
		for (int i = 0; i < intArray.length; i++) {
			if (intArray[i] == j)
				return true;
		}
		return false;
	}

	public int distanceTo(int x1, int y1, int x2, int y2) {
		double dx = Math.abs(x1 - x2);
		double dy = Math.abs(y1 - y2);
		dx = Math.pow(dx, 2);
		dy = Math.pow(dy, 2);
		return (int) Math.sqrt(dx + dy);
	}

	public int[] stringToIntArray(String str) {
		try {
			String[] str2 = str.split(",");
			int[] val = new int[str2.length];
			for (int i = 0; i < str2.length; i++) {
				try {
					val[i] = Integer.parseInt(str2[i]);
				} catch (Exception e) {};
			}
			return val;
		} catch (Exception e) { return null; }
	}

	public void getAccountSettings() {
    	try {
			Properties account = new Properties();
			account.load(new FileInputStream("./fightmode.ini"));
			fightMode = Integer.parseInt(account.getProperty("fightMode"));
			System.out.println("Using combat style: " + fightMode);
        } catch (Exception e) {
        	System.out.println("Failed to load account settings.");
            System.out.println("Do we have permission?");
        }
	}
}